﻿using System;
using System.Collections.Generic;
using System.Linq;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Statistics;
using NHibernate;
using NHibernate.Criterion;

namespace ControleRepresentante.Logic.Repositories
{
    public interface IUsuariosHolderRepository<TModel, TStatistics> : IDetailsHolderRepository<TModel, TStatistics>
        where TModel : UsuariosHolder where TStatistics : IStatistics
    {
        Dictionary<Guid, string> GetModelNames();
        Dictionary<Guid, string> GetModelNames(string search);
    }

    public abstract class UsuariosHolderRepository<TModel, TStatistics, TError> : DetailsHolderRepository<TModel, TStatistics, TError>, IUsuariosHolderRepository<TModel, TStatistics>
        where TModel : UsuariosHolder 
        where TStatistics : IStatistics
    {
        protected UsuariosHolderRepository(IRepositoryConfiguration repositoryConfiguration, ISession session)
            : base(repositoryConfiguration, session)
        {
        }

        protected override IQueryOver<TModel, TModel> GetModelsQueryOver(IQueryOver<TModel, TModel> queryOver)
        {
            IEnumerable<TModel> models = User.Filtros.OfType<TModel>();
            if (models.Any())
            {
                return queryOver.And(Restrictions.In(Projections.Property<TModel>(x => x.Id), models.Select(y => y.Id).ToArray()));
            }
            return DoGetModelsQueryOver(queryOver);
        }

        protected abstract IQueryOver<TModel, TModel> DoGetModelsQueryOver(IQueryOver<TModel, TModel> queryOver);

        protected override IQueryOver<TModel, TModel> DoGetModelByIdQueryOver(IQueryOver<TModel, TModel> queryOver, Guid id)
        {
            IEnumerable<TModel> models = User.Filtros.OfType<TModel>();

            if (models.Any() && !models.Any(x => x.Id == id))
            {
                throw new RestrictedAreaException();
            }

            return InternalDoGetModelByIdQueryOver(queryOver, id);
        }

        protected virtual IQueryOver<TModel, TModel> InternalDoGetModelByIdQueryOver(IQueryOver<TModel, TModel> queryOver, Guid id)
        {
            return queryOver;
        }

        public abstract Dictionary<Guid, string> GetModelNames();
        public abstract Dictionary<Guid, string> GetModelNames(string search);
    }
}